Constrain the deferred declaration path to a dotted name (#24)#39
Merged
Conversation
parse_deferred_decl read the path with parse_expr(0), a full expression
parse. No consumer could use that expressiveness — qualified-reference
collection extracts only Expr::QualifiedName, the CLI test-plan builder
matches only Ident/MemberAccess/QualifiedName (anything else silently
dropped the deferred spec from the plan), and both analyzers' regex
lanes capture a flat dotted name. Meanwhile expression-shaped paths
(deferred Foo("x"), deferred Foo = "x", deferred (Foo)) parsed with
zero diagnostics, hiding spec errors.
The path is now a dotted name with an optional use-alias qualifier:
Name, Name.field.sub, alias/Name, alias/Name.field. In declaration
position there is no division to disambiguate from, so `/` always
introduces a qualifier (mirroring `fulfils alias/Name`, 9cd9463).
The path stays an Expr (Ident/QualifiedName/MemberAccess), so
qualified-reference collection and the WASM AST mirror are unchanged.
The path stops before a dangling `.` so the declaration still forms —
the location-hint check keeps covering the line (warning named after
the TypeScript capture, dot included) and the leftover token errors at
declaration level, identically in both front ends now that the
extension surfaces WASM parse diagnostics (#25). Line guards keep a
dangling `.` or `/` from absorbing the next declaration's leading
keyword, since newlines are not tokens and keywords are word tokens.
The quoted location hint becomes part of the grammar: `deferred
Foo.bar "detailed/foo.allium"` previously emitted "expected
declaration ..., found string" even though both analyzers' suppression
predicate and the check-tool behaviour spec bless the form. It now
parses, stored as location_hint on DeferredDecl, and must share the
declaration's line.
Documents the accepted forms in the v3 language reference, updates the
parity scope in rust-checker-parity.md §6, and adds the grammar rule to
the check-tool behaviour spec. The tree-sitter grammar mirror
(juxt/tree-sitter-allium deferred_declaration) needs a matching change.
Closes #24.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
yavorpanayotov
added a commit
to juxt/tree-sitter-allium
that referenced
this pull request
Jun 12, 2026
deferred_declaration read its path as $._expression, so calls, comparisons, and parenthesised forms parsed as deferred paths, and the qualified form billing/InvoiceWorkflow parsed as division. The reference parser constrained the path in juxt/allium-tools#24 (juxt/allium-tools#39); this mirrors that grammar: deferred_path: identifier ('/' identifier)? ('.' identifier)* with an optional trailing string_literal location hint (`deferred Foo.bar "detailed/foo.allium"`), now part of the grammar on both sides. Known divergence from the reference parser: the path and hint are required to sit on one line there, which this grammar does not enforce (newlines are extras). Corpus: dotted-path expectation updated to the new node shape; new cases for the qualified path, the quoted hint, and an :error test for an expression-shaped path. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #24. Implements the direction agreed in the issue discussion, including option (a) for the quoted location hint: the deferred path is constrained at the parser level to a dotted name with an optional
use-alias qualifier, and the quoted location hint becomes part of the grammar.What changes
Grammar.
deferredacceptsName,Name.field.sub,alias/Name,alias/Name.field, optionally followed by a quoted location hint on the same line. Calls, operators, comparisons, and parenthesised forms no longer parse as paths./always introduces a qualifier and a missing name after it is a hard error — same rationale asfulfils alias/MyContract(9cd9463)..: the declaration still forms (so the location-hint check keeps covering the line, warning under the TypeScript capture's name, dot included) and the leftover token errors at declaration level — identically in both front ends now that the extension surfaces WASM parse diagnostics (TypeScript analyzer discards WASM parse diagnostics #25/Surface WASM parse diagnostics in the TS analyzer (#25) #27)..or/from absorbing the next declaration's leading keyword across lines (newlines are not tokens and keywords are word tokens — caught while testing, with regression tests on both).deferred Foo.bar "detailed/foo.allium"previously emittedexpected declaration ..., found stringeven though both analyzers' suppression predicate and the check-tool behaviour spec bless the form. It now parses, stored aslocation_hintonDeferredDecl.AST. The path stays an
Expr(Ident/QualifiedName/MemberAccess), per constraint 1 on the issue —collect_qualified_referencesand the WASM adapter consume it unchanged.DeferredDeclgainslocation_hint: Option<StringLiteral>; the TS mirror type follows.Behaviour matrix (verified against both built analyzers):
deferred Foo.bardeferred billing/InvoiceWorkflowbillingbilling(unchanged)deferred Foo.bar "detailed/foo.allium"deferred Foo("x"),deferred Foo = "x"deferred (Foo)expected deferred name, found '(', both sidesdeferred Foo.Foo.+ one shared parse errordeferred billing/expected deferred name after '/'Docs
rust-checker-parity.md§6: parity scope updated — malformed deferred lines now produce identical diagnostic sets on both sides.allium-check-tool-behaviour.allium: newDeferredPathConstrainedToDottedNamerule.Cross-repo follow-up
juxt/tree-sitter-alliummirrors the old grammar (deferred_declaration: seq("deferred", field("path", $._expression)), grammar.js:186). Once the shape is agreed here, the sibling change is roughly:Verification
cargo test --workspace: 559 tests pass (374 in the parser crate — 9 new grammar tests, 1 new analysis test).npm run testagainst the rebuilt WASM: 330 pass (2 new wasm-adapter tests);npm run lint: 0 errors (2 pre-existing warnings on main).docs/versioning.mdrule 1 this is a grammar change → minor bump (3.3.0) at release time; not bumped in this PR, matching how 9cd9463 landed.🤖 Generated with Claude Code